package com.weiyi.weiman.ascpect;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.weiyi.weiman.annotation.Log;
import com.weiyi.weiman.domain.Const.UserConst;
import com.weiyi.weiman.domain.dto.ResultInfo;
import com.weiyi.weiman.utils.HttpContextUtil;
import com.weiyi.weiman.utils.IPUtils;
import com.weiyi.weiman.utils.JWTUtils;
import com.weiyi.weiman.utils.RedisUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import sys.SysUserLog;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @Author zhang
 * @Date 2021/5/14 上午11:05
 * @Description
 * @Version 1.0
 **/
@Aspect
@Component
public class UserLogAspect {

    @Autowired
    private RedisUtils redisUtils;

    @Pointcut("@annotation(com.weiyi.weiman.annotation.Log)")
    public void pointcut(){ }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) {
        Object result = null;
        Long beginTime = System.currentTimeMillis();
        try {
            result = point.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        Long time = System.currentTimeMillis() - beginTime;
        if (((ResultInfo) result).getCode() == 2000)
            saveLog(point, time, "true");
        else
            saveLog(point, time, "false");
        return result;
    }

    private void saveLog(ProceedingJoinPoint joinPoint, Long time, String succeed) {
        // 获取request
        HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
        String token = request.getHeader("Authorization");
        if (!StringUtils.isEmpty(token) && JWTUtils.validateJWT(token)) {
            String userId = JWTUtils.parseJWT(token).getSubject();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysUserLog userLog = new SysUserLog();
            Log logAnnotation = method.getAnnotation(Log.class);
            if (logAnnotation != null) {
                userLog.setOperation(logAnnotation.value());
            }
            // 请求的类名
            String className = joinPoint.getTarget().getClass().getName();
            // 请求的方法名
            String methodName = signature.getName();
            userLog.setOperation(className + "." + methodName + "()");
            // 获取接口请求方式
            userLog.setMethod(request.getMethod());
            // 请求的方法参数值
            Object[] args = joinPoint.getArgs();
            LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
            String[] paramNames = u.getParameterNames(method);
            if (args != null && paramNames != null) {
                String params = "";
                for (int i = 0; i < args.length; i++) {
                    if (!"request".equals(paramNames[i]))
                        params += paramNames[i] + ": " + args[i];
                }
                userLog.setParams(params);
            }
            // 请求的uri路径
            userLog.setUri(request.getRequestURI());

            userLog.setUserId(Long.parseLong(userId));
            userLog.setIp(IPUtils.getIpAddr(request));
            userLog.setSucceed(succeed);
            userLog.setTime(time);
            userLog.setGwtCreate(new Date());
            redisUtils.lRightPush(UserConst.USER_LOG_PRE + userId, JSON.toJSONString(userLog));
        }
    }

}
